"""服务监控模块，负责监控系统性能和健康状态"""
import time
import psutil
import prometheus_client
from prometheus_client import Counter, Gauge, Histogram
from typing import Optional
from threading import Thread
from fin_senti_entity_platform.utils.logger import get_logger
from fin_senti_entity_platform.utils.config_loader import get_config

logger = get_logger(__name__)

class ServiceMonitor:
    """服务监控器"""
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(ServiceMonitor, cls).__new__(cls)
        return cls._instance
    
    def __init__(self):
        if not hasattr(self, '_initialized'):
            self.config = get_config()
            self.is_running = False
            self.monitor_thread = None
            self.check_interval = self.config.get('monitor', {}).get('check_interval', 60)  # 秒
            
            # 初始化Prometheus指标
            self._init_prometheus_metrics()
            
            # 启动Prometheus指标服务
            metrics_port = self.config.get('monitor', {}).get('metrics_port', 8001)
            prometheus_client.start_http_server(metrics_port)
            logger.info(f"Prometheus指标服务已启动在端口 {metrics_port}")
            
            self._initialized = True
    
    def _init_prometheus_metrics(self):
        """初始化Prometheus指标"""
        # 系统资源指标
        self.system_cpu_usage = Gauge('fin_senti_system_cpu_usage', '系统CPU使用率')
        self.system_memory_usage = Gauge('fin_senti_system_memory_usage', '系统内存使用率')
        self.system_disk_usage = Gauge('fin_senti_system_disk_usage', '系统磁盘使用率', ['path'])
        
        # 服务指标
        self.service_request_count = Counter('fin_senti_service_request_count', '服务请求计数', ['endpoint', 'method', 'status'])
        self.service_request_latency = Histogram('fin_senti_service_request_latency', '服务请求延迟(秒)', ['endpoint'])
        self.service_error_count = Counter('fin_senti_service_error_count', '服务错误计数', ['error_type'])
        
        # 模型指标
        self.model_inference_count = Counter('fin_senti_model_inference_count', '模型推理计数', ['model_type', 'status'])
        self.model_inference_latency = Histogram('fin_senti_model_inference_latency', '模型推理延迟(秒)', ['model_type'])
        self.model_memory_usage = Gauge('fin_senti_model_memory_usage', '模型内存使用(MB)', ['model_type'])
        
        # 数据处理指标
        self.data_processing_count = Counter('fin_senti_data_processing_count', '数据处理计数', ['source', 'status'])
        self.data_processing_latency = Histogram('fin_senti_data_processing_latency', '数据处理延迟(秒)', ['source'])
    
    def start(self):
        """启动监控"""
        if self.is_running:
            logger.warning("监控已经在运行中")
            return
        
        self.is_running = True
        self.monitor_thread = Thread(target=self._monitor_loop, daemon=True)
        self.monitor_thread.start()
        logger.info(f"服务监控已启动，检查间隔: {self.check_interval}秒")
    
    def stop(self):
        """停止监控"""
        if not self.is_running:
            logger.warning("监控未运行")
            return
        
        self.is_running = False
        if self.monitor_thread:
            self.monitor_thread.join(timeout=5)
        logger.info("服务监控已停止")
    
    def _monitor_loop(self):
        """监控循环"""
        while self.is_running:
            try:
                # 收集系统资源指标
                self._collect_system_metrics()
                
                # 收集服务健康指标
                self._collect_health_metrics()
                
                # 等待下一次检查
                time.sleep(self.check_interval)
            except Exception as e:
                logger.error(f"监控循环异常: {str(e)}")
                # 避免异常导致监控循环终止
                time.sleep(1)
    
    def _collect_system_metrics(self):
        """收集系统资源指标"""
        # CPU使用率
        cpu_usage = psutil.cpu_percent(interval=0.1)
        self.system_cpu_usage.set(cpu_usage)
        
        # 内存使用率
        memory = psutil.virtual_memory()
        self.system_memory_usage.set(memory.percent)
        
        # 磁盘使用率
        for partition in psutil.disk_partitions():
            try:
                usage = psutil.disk_usage(partition.mountpoint)
                self.system_disk_usage.labels(path=partition.mountpoint).set(usage.percent)
            except (PermissionError, FileNotFoundError):
                # 某些分区可能无法访问
                continue
    
    def _collect_health_metrics(self):
        """收集服务健康指标"""
        # 这里可以添加自定义的健康检查逻辑
        # 例如检查数据库连接、模型服务可用性等
        pass
    
    def record_request(self, endpoint: str, method: str, status: int, latency: float):
        """记录请求指标
        
        Args:
            endpoint: 端点
            method: 请求方法
            status: 状态码
            latency: 延迟(秒)
        """
        self.service_request_count.labels(endpoint=endpoint, method=method, status=status).inc()
        self.service_request_latency.labels(endpoint=endpoint).observe(latency)
    
    def record_error(self, error_type: str):
        """记录错误指标
        
        Args:
            error_type: 错误类型
        """
        self.service_error_count.labels(error_type=error_type).inc()
    
    def record_model_inference(self, model_type: str, status: str, latency: float, memory_usage: Optional[float] = None):
        """记录模型推理指标
        
        Args:
            model_type: 模型类型
            status: 状态
            latency: 延迟(秒)
            memory_usage: 内存使用(MB)
        """
        self.model_inference_count.labels(model_type=model_type, status=status).inc()
        self.model_inference_latency.labels(model_type=model_type).observe(latency)
        if memory_usage is not None:
            self.model_memory_usage.labels(model_type=model_type).set(memory_usage)
    
    def record_data_processing(self, source: str, status: str, latency: float):
        """记录数据处理指标
        
        Args:
            source: 数据源
            status: 状态
            latency: 延迟(秒)
        """
        self.data_processing_count.labels(source=source, status=status).inc()
        self.data_processing_latency.labels(source=source).observe(latency)